﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Eagleshoes.PackingBarcode.CartonService;
using Eagleshoes.PackingBarcode.Properties;

namespace Eagleshoes.PackingBarcode.PackagingScan
{
    public partial class PackagingOnlineScanForm : Form
    {
        public PackagingOnlineScanForm()
        {
            InitializeComponent();
        }

        #region Fields

        private static MyPackagingCarton packaging;
        private readonly Scanner scaner = new Scanner();
        private bool hasScandPackaging;

        private Action<string, string, string, byte[]> msgAction;
        private Action<String> scanAction;

        #region 声音资源

        private readonly byte[] bytesBoxErr = Resources.装箱错误;
        private readonly byte[] bytesConnectErr = Resources.通讯错误;
        private readonly byte[] bytesDing = Resources.叮;
        private readonly byte[] bytesFull = Resources.满箱;
        private readonly byte[] bytesNullPackaging = Resources.查无包装资料;
        private readonly byte[] bytesScanBox = Resources.请扫内盒;

        #endregion

        #endregion

        #region Form Events

        private void PackagingOnlineScanForm_Load(object sender, EventArgs e)
        {
            ControlBox = false;
            WindowState = FormWindowState.Maximized;

            scanAction = Scan;
            msgAction = sendMessage;

            scaner.DecodeEvent += scaner_DecodeEvent;
            scaner.Start();
        }

        private void scaner_DecodeEvent(object sender, DecodeEventArgs e)
        {
            BeginInvoke(scanAction, e.Barcode.Trim('\n', '\r', '\t', '\0', ' '));
        }

        private void PackagingOnlineScanForm_Closed(object sender, EventArgs e)
        {
            scaner.Stop();
            scaner.DecodeEvent -= scaner_DecodeEvent;
        }

        private void PackagingOnlineScanForm_KeyUp(object sender, KeyEventArgs e)
        {
            switch (e.KeyValue)
            {
                case 122:
                    if (packaging == null)
                    {
                        Close();
                    }
                    else
                    {
                        sendMessage(string.Empty, string.Empty, "请扫描外箱", bytesDing);
                        Reset();
                    }
                    break;
                case 123:
                    sendMessage(string.Empty, string.Empty, "请扫描外箱", bytesDing);
                    Reset();
                    break;
            }
        }

        private void btnReturn_Click(object sender, EventArgs e)
        {
            Close();
        }


        private void btnReset_Click(object sender, EventArgs e)
        {
            sendMessage(string.Empty, string.Empty, "请扫描外箱", bytesDing);
            Reset();
        }

        #endregion

        #region Methods

        private void sendMessage(string barcode, string box, string msg, byte[] snd)
        {
            tbxCartonBarcode.Text = barcode;
            tbxBoxBarcode.Text = box;
            sbMsg.Text = msg;
            if (snd.Length > 0)
            {
                Win32.sndPlaySound(snd, Win32.SND_ASYNC | Win32.SND_MEMORY);
            }
        }

        private string convertToString(MyPackagingCarton pc)
        {
            if (pc == null)
            {
                return string.Empty;
            }
            var sb = new StringBuilder();
            foreach (MyPackagingCarton.MyPackagingBox box1 in pc.Boxes.Values)
            {
                sb.AppendLine(string.Format("{0}[{1}]\t\t{2}/{3}", box1.BoxBarcode, box1.Spec, box1.ScanedQuantities, box1.Quantities));
            }
            return sb.ToString();
        }

        private void Scan(string barcode)
        {
            scaner.Stop();
            if (!hasScandPackaging)
            {
                ScanPackagingCarton(barcode);
            }
            else
            {
                ScanPackagingBox(barcode);
            }
        }


        private void ScanPackagingCarton(string barcode)
        {
            tbxCartonBarcode.Text = barcode;

            Program.CartonClient.BeginGetPackagingCartonOnline(barcode, ar =>
                {
                    var cs = (CartonService.CartonService) ar.AsyncState;

                    PackagingCarton pc;
                    try
                    {
                        pc = cs.EndGetPackagingCartonOnline(ar);
                    }
                    catch
                    {
                        BeginInvoke(msgAction, string.Empty, string.Empty, "通讯错误", bytesConnectErr);
                        Reset();
                        return;
                    }

                    if (pc == null)
                    {
                        BeginInvoke(msgAction, string.Empty, "没有找到的包装资料", string.Empty, bytesNullPackaging);
                        Reset();
                        return;
                    }

                    packaging = new MyPackagingCarton(pc);

                    if ((from boxcode in packaging.Boxes.Keys
                         select boxcode).Any(boxcode => boxcode.Contains("已扫描")))
                    {
                        BeginInvoke(msgAction, packaging.CartonBarcode, convertToString(packaging), "满箱", bytesFull);
                    }
                    else
                    {
                        BeginInvoke(msgAction, packaging.CartonBarcode, convertToString(packaging), "请扫内盒条码", bytesScanBox);
                    }

                    hasScandPackaging = true;

                    scaner.Stop();
                    scaner.Start();
                }, Program.CartonClient);
        }


        private void ScanPackagingBox(string barcode)
        {
            MyPackagingCarton.MyPackagingBox box;
            try
            {
                box = packaging.Boxes[barcode];

                if (box.ScanedQuantities >= box.Quantities)
                {
                    throw new KeyNotFoundException();
                }
            }
            catch
            {
                sendMessage(packaging.CartonBarcode, convertToString(packaging), "装箱错误", bytesBoxErr);
                scaner.Stop();
                scaner.Start();
                return;
            }

            box.ScanedQuantities++;
            if (box.ScanedQuantities < box.Quantities || !packaging.IsFull)
            {
                sendMessage(packaging.CartonBarcode, convertToString(packaging), "请继续扫描内盒", bytesDing);
                scaner.Stop();
                scaner.Start();
                return;
            }


            //以下为满箱处理
            packaging.IsScan = true;
            packaging.ScanTime = DateTime.Now;
            var list = new List<MyPackagingCarton>();
            list.Add(packaging);
            try
            {
                if (MyPackagingCarton.SaveScanedPackagingCartonOnline(list))
                {
                    Win32.sndPlaySound(bytesDing, Win32.SND_ASYNC | Win32.SND_MEMORY);
                    sendMessage(string.Empty, string.Empty, "满箱，请继续扫描外箱！", bytesFull);
                }
                else
                {
                    throw new Exception();
                }
            }
            catch
            {
                sendMessage(string.Empty, string.Empty, "通讯错误，请重新扫描外箱！", bytesConnectErr);
            }
            finally
            {
                Reset();
            }
        }

        private void Reset()
        {
            packaging = null;
            hasScandPackaging = false;
            scaner.Stop();
            scaner.Start();
        }

        #endregion
    }
}